package util;



import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import exception.SystemException;

/**
 * 暗号化・復号化用のメソッドを提供するクラス
 * @author kenta
 *
 */
public class Encrypter {

	//コンストラクタで作成したオブジェクト持ち回り用
	private Cipher cipher;
	private PBEKeySpec keySpec;
	private PBEParameterSpec paramSpec;
	private SecretKey key;
	
	//暗号化のためのソルト
    private final byte[] salt = {(byte)0x39, (byte)0x4e, (byte)0xa2, (byte)0x18,
            (byte)0x79, (byte)0x22, (byte)0x10, (byte)0xfe};
    //暗号化のためのイテレーション
    private final int iteration = 10;	
	//暗号化のためのパスワード
	private final char[] password = "ojt12345".toCharArray();
	
	/**
	 * コンストラクタ
	 * @throws SystemException システム例外
	 */
	public Encrypter()throws SystemException{
		try{
		     //Cipherオブジェクトの生成 
		     this.cipher = Cipher.getInstance("PBEWithMD5AndDES");
		 
		     //パスワードを使って鍵を生成
		     this.keySpec = new PBEKeySpec(this.password);
		     SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
		     this.key = keyFac.generateSecret(this.keySpec);
		 
		     //saltとiterationを使ってアルゴリズムパラメータを生成
		     this.paramSpec = new PBEParameterSpec(this.salt, this.iteration);
		}
		catch(Exception e){
			throw new SystemException(e.getMessage());
		}
	}
	
	/**
	 * 暗号化メソッド
	 * @param String 暗号化対象の文字列
	 * @return String 暗号化した文字列
	 * @throws SystemException システム例外
	 */
	public byte[] encrypt(String target)throws SystemException{
		byte[] encrypted;
		
		try{
			this.cipher.init(Cipher.ENCRYPT_MODE, this.key, this.paramSpec);
			encrypted = this.cipher.doFinal(target.getBytes());
		}
		catch (Exception e ){
			throw new SystemException(e.getMessage());
		}
		return encrypted;
	}
	
	/**
	 * 復号化メソッド
	 * @param String 復号化対象の文字列
	 * @return String 復号化した文字列
	 * @throws SystemException システム例外
	 */
	public String decrypt(byte[] target)throws SystemException{
		String decrypted;
		
		try{
			this.cipher.init(Cipher.DECRYPT_MODE, this.key, this.paramSpec);
			decrypted = new String(this.cipher.doFinal(target));
		}
		catch (Exception e){
			throw new SystemException(e.getMessage());
		}
		return decrypted;
	}
}
